package com.wusiwei.controller;

import com.wusiwei.common.PageRequest;
import com.wusiwei.common.PageResult;
import com.wusiwei.common.Result;
import com.wusiwei.entity.Invoice;
import com.wusiwei.entity.Order;
import com.wusiwei.service.InvoiceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 发票控制器
 */
@RestController
@RequestMapping("/api/invoices")
@Tag(name = "发票管理", description = "发票管理相关的API接口")
@Slf4j
public class InvoiceController {

    @Autowired
    private InvoiceService invoiceService;

    /**
     * 新增发票
     *
     * @param invoice 发票对象
     * @return 操作结果
     */
    @Operation(summary = "创建新发票", description = "创建一个新的发票记录")
    @PostMapping
    public Result<Invoice> create(@RequestBody Invoice invoice) {
        try {
            Invoice createdInvoice = invoiceService.create(invoice);
            return Result.success(createdInvoice);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 更新发票
     *
     * @param invoice 发票对象
     * @return 操作结果
     */
    @Operation(summary = "更新发票信息", description = "根据ID更新发票信息")
    @PutMapping("/{id}")
    public Result<Invoice> update(
            @Parameter(description = "发票ID") @PathVariable Integer id,
            @RequestBody Invoice invoice) {
        // 确保ID正确设置
        invoice.setId(Long.valueOf(id));
        log.info("更新发票，ID: {}, 发票内容: {}", id, invoice);
        return invoiceService.update(invoice);
    }

    /**
     * 删除发票
     *
     * @param id 发票ID
     * @return 操作结果
     */
    @Operation(summary = "删除发票", description = "根据ID删除发票")
    @DeleteMapping("/{id}")
    public Result<Void> delete(@Parameter(description = "发票ID") @PathVariable Integer id) {
        return invoiceService.delete(Long.valueOf(id));
    }

    /**
     * 根据ID查询发票
     *
     * @param id 发票ID
     * @return 发票对象
     */
    @Operation(summary = "获取发票详情", description = "根据发票ID获取发票详情信息")
    @GetMapping("/{id}")
    public Result<Invoice> getById(@Parameter(description = "发票ID") @PathVariable Integer id) {
        try {
            log.info("查询发票详情，ID: {}", id);
            Invoice invoice = invoiceService.getById(Long.valueOf(id));
            if (invoice != null) {
                log.info("发票查询成功，ID: {}, 明细数量: {}", id,
                        invoice.getDetails() != null ? invoice.getDetails().size() : 0);
                return Result.success(invoice);
            } else {
                log.warn("未找到发票，ID: {}", id);
                return Result.error("发票不存在");
            }
        } catch (Exception e) {
            log.error("查询发票详情失败，ID: {}", id, e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 查询所有发票
     *
     * @return 发票列表
     */
    @Operation(summary = "获取所有发票", description = "获取系统中所有发票记录")
    @GetMapping
    public Result<List<Invoice>> list() {
        try {
            List<Invoice> invoices = invoiceService.list();
            return Result.success(invoices);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 分页查询发票
     *
     * @param pageRequest 分页参数
     * @return 发票分页列表
     */
    @Operation(summary = "分页查询发票", description = "根据分页参数获取发票记录")
    @GetMapping("/page")
    public Result<PageResult<Invoice>> page(@Parameter(description = "分页请求参数") PageRequest pageRequest) {
        try {
            log.info("分页查询发票, 参数: {}", pageRequest);
            PageResult<Invoice> pageResult = invoiceService.page(pageRequest);
            return Result.success(pageResult);
        } catch (Exception e) {
            log.error("分页查询发票失败", e);
            return Result.error("分页查询发票失败: " + e.getMessage());
        }
    }

    /**
     * 搜索发票
     *
     * @param keyword 关键字
     * @return 发票列表
     */
    @Operation(summary = "搜索发票", description = "根据关键字搜索发票记录")
    @GetMapping("/search")
    public Result<List<Invoice>> search(@Parameter(description = "搜索关键字") String keyword) {
        try {
            List<Invoice> invoices = invoiceService.search(keyword);
            return Result.success(invoices);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 根据发票类型过滤发票
     *
     * @param type 发票类型
     * @return 过滤后的发票列表
     */
    @Operation(summary = "根据发票类型过滤发票", description = "根据发票类型过滤发票记录")
    @GetMapping("/filter")
    public Result<List<Invoice>> filter(
            @Parameter(description = "发票类型") @RequestParam String type) {
        try {
            List<Invoice> invoices = invoiceService.filter(type);
            return Result.success(invoices);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 验证发票
     *
     * @param id 发票ID
     * @return 验证结果
     */
    @Operation(summary = "验证发票", description = "验证指定发票的验证状态")
    @PostMapping("/{id}/verify")
    public Result<String> verify(@Parameter(description = "发票ID") @PathVariable Integer id) {
        try {
            String result = invoiceService.verify(Long.valueOf(id));
            return Result.success(result);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 根据条件查询发票
     *
     * @param condition 查询条件
     * @return 发票列表
     */
    @Operation(summary = "根据条件查询发票", description = "根据多种条件组合查询发票记录")
    @PostMapping("/condition")
    public Result<List<Invoice>> findByCondition(@Parameter(description = "查询条件") @RequestBody Map<String, Object> condition) {
        try {
            log.info("根据条件查询发票, 条件: {}", condition);
            List<Invoice> invoices = invoiceService.findByCondition(condition);
            return Result.success(invoices);
        } catch (Exception e) {
            log.error("根据条件查询发票失败", e);
            return Result.error("根据条件查询发票失败: " + e.getMessage());
        }
    }

    /**
     * 获取发票统计信息
     *
     * @return 发票统计信息
     */
    @Operation(summary = "获取发票统计信息", description = "获取发票的统计数据，包括总数、总金额等")
    @GetMapping("/statistics")
    public Result<Map<String, Object>> statistics() {
        try {
            Map<String, Object> statistics = invoiceService.getStatistics();
            return Result.success(statistics);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }

    /**
     * 更新发票文件路径
     *
     * @param id          发票ID
     * @param requestBody 文件路径
     * @return 更新结果
     */
    @Operation(summary = "更新发票文件路径", description = "更新指定发票的文件路径")
    @PatchMapping("/{id}/file-path")
    public Result<Void> updateFilePath(
            @Parameter(description = "发票ID") @PathVariable Integer id,
            @Parameter(description = "文件路径信息") @RequestBody Map<String, String> requestBody) {
        try {
            String filePath = requestBody.get("filePath");
            if (filePath == null || filePath.trim().isEmpty()) {
                return Result.error("文件路径不能为空");
            }

            log.info("更新发票文件路径, ID: {}, 文件路径: {}", id, filePath);
            return invoiceService.updateFilePath(Long.valueOf(id), filePath);
        } catch (Exception e) {
            log.error("更新发票文件路径失败", e);
            return Result.error("更新发票文件路径失败: " + e.getMessage());
        }
    }

    /**
     * 导出发票
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return 导出的发票
     */
    @Operation(summary = "导出发票", description = "根据日期范围导出发票数据")
    @GetMapping("/export")
    public ResponseEntity<byte[]> export(
            @Parameter(description = "开始日期，格式：yyyy-MM-dd") @RequestParam(required = false) String startDate,
            @Parameter(description = "结束日期，格式：yyyy-MM-dd") @RequestParam(required = false) String endDate) {
        try {
            log.info("导出发票数据, 日期范围: {} - {}", startDate, endDate);

            byte[] fileContent = invoiceService.exportInvoices(startDate, endDate);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", "invoices.xlsx");

            return new ResponseEntity<>(fileContent, headers, HttpStatus.OK);
        } catch (Exception e) {
            log.error("导出发票失败", e);
            // 返回带有错误信息的响应，而不是抛出异常
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_PLAIN);
            return new ResponseEntity<>(("导出失败: " + e.getMessage()).getBytes(),
                    headers, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 根据日期范围获取发票
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @return 发票列表
     */
    @GetMapping("/date-range")
    @Operation(summary = "根据日期范围获取发票", description = "根据开始日期和结束日期查询发票")
    public Result<List<Invoice>> getInvoiceByDateRange(
            @Parameter(description = "开始日期，格式：yyyy-MM-dd") @RequestParam String startDate,
            @Parameter(description = "结束日期，格式：yyyy-MM-dd") @RequestParam String endDate) {
        try {
            log.info("根据日期范围查询发票, 开始日期: {}, 结束日期: {}", startDate, endDate);
            List<Invoice> invoices = invoiceService.findByDateRange(startDate, endDate);
            return Result.success(invoices);
        } catch (Exception e) {
            log.error("根据日期范围查询发票失败", e);
            return Result.error("根据日期范围查询发票失败: " + e.getMessage());
        }
    }

    /**
     * 部分更新发票信息
     *
     * @param id   发票ID
     * @param data 部分发票数据
     * @return 更新结果
     */
    @PatchMapping("/{id}/partial")
    @Operation(summary = "部分更新发票信息", description = "根据ID部分更新发票信息")
    public Result<Invoice> updateInvoicePartial(
            @Parameter(description = "发票ID") @PathVariable Integer id,
            @RequestBody Map<String, Object> data) {
        try {
            log.info("部分更新发票信息, ID: {}, 数据: {}", id, data);
            Invoice invoice = invoiceService.partialUpdate(Long.valueOf(id), data);
            return Result.success(invoice);
        } catch (Exception e) {
            log.error("部分更新发票信息失败", e);
            return Result.error("部分更新发票信息失败: " + e.getMessage());
        }
    }

    /**
     * 根据发票号码查询
     *
     * @param invoiceNumber 发票号码
     * @return 发票信息
     */
    @GetMapping("/number")
    @Operation(summary = "根据发票号码查询", description = "根据发票号码查询发票信息")
    public Result<Invoice> findInvoiceByNumber(
            @Parameter(description = "发票号码") @RequestParam String invoiceNumber) {
        try {
            log.info("根据发票号码查询发票, 发票号码: {}", invoiceNumber);
            Invoice invoice = invoiceService.findByInvoiceNumber(invoiceNumber);
            if (invoice != null) {
                return Result.success(invoice);
            } else {
                return Result.error("未找到发票号码为 " + invoiceNumber + " 的发票");
            }
        } catch (Exception e) {
            log.error("根据发票号码查询发票失败", e);
            return Result.error("根据发票号码查询发票失败: " + e.getMessage());
        }
    }

    /**
     * 批量删除发票
     *
     * @param ids 发票ID列表
     * @return 操作结果
     */
    @Operation(summary = "批量删除发票", description = "根据ID列表批量删除发票")
    @DeleteMapping("/batch")
    public Result<Void> batchDelete(@Parameter(description = "发票ID列表") @RequestBody List<Long> ids) {
        try {
            log.info("批量删除发票, IDs: {}", ids);
            boolean success = invoiceService.batchDelete(ids);
            if (success) {
                return Result.success();
            } else {
                return Result.error("批量删除发票失败");
            }
        } catch (Exception e) {
            log.error("批量删除发票失败", e);
            return Result.error("批量删除发票失败: " + e.getMessage());
        }
    }

    /**
     * 获取发票关联的订单
     *
     * @param id 发票ID
     * @return 关联的订单列表
     */
    @Operation(summary = "获取发票关联的订单", description = "根据发票ID获取关联的订单列表")
    @GetMapping("/{id}/related-orders")
    public Result<List<Order>> getRelatedOrders(@Parameter(description = "发票ID") @PathVariable Integer id) {
        try {
            log.info("获取发票关联订单, 发票ID: {}", id);
            List<Order> orders = invoiceService.getRelatedOrders(Long.valueOf(id));
            return Result.success(orders);
        } catch (Exception e) {
            log.error("获取发票关联订单失败, 发票ID: {}", id, e);
            return Result.error("获取发票关联订单失败: " + e.getMessage());
        }
    }
} 